Quote Retention & Reuse
When a quote request succeeds, the system stores it keyed by the combination of contact.email and contact.ratingZipCode.
How Retrieval Works
- If a NEW email/zip pair is used, a fresh quote record is created and returned.
- If the SAME email/zip pair was previously quoted, the existing quote is transitioned into a “return” state and replaced with the new request data.
Pet & Coverage Replacement
- All prior pets and coverage selections tied to that email/zip pair are removed.
- The pets and coverages from the latest request fully replace the old ones—there is no merge.
- This ensures partners can safely re-post the same pet (idempotent for unchanged data) or update details without manually clearing prior state.
Typical Partner Flow
- Partner collects pet + contact info and posts initial quote.
- Partner later re-issues a quote (e.g., user revisits) with identical or updated pet information.
- The platform returns the updated quote reflecting ONLY the newest pets and coverage selections.
Because a coverage is often not yet finalized at first interaction, re-quoting with the same pet details effectively refreshes pricing without unexpected historical carryover.
Implications
- Do not rely on earlier pets persisting if you omit them in a subsequent request—always send the authoritative full set you want represented.
- To remove a pet, simply exclude it from the next quote request payload.
- If you need historical comparisons, store snapshots on your side before re-posting.
Best Practices
- Always treat the quote request body as the complete desired state for pets & coverage selections.
- Cache the current
quoteIdclient-side, but be prepared for a refreshed response returning the same or a newquoteIddepending on system logic. - Log re-quote events (email/zip reuse) for analytics on user revisit behavior.
Analytics Fields
Field path: top-level object key: analytics
The analytics block allows attaching campaign attribution metadata to the quote record. It is treated as a full replacement object each time you POST or re‑POST a quote (or use any endpoint that accepts it). If you omit analytics on an update (even if it was present previously), the previously stored analytics values are cleared / overwritten.
| Property | Required | Source | Description | Example |
|---|---|---|---|---|
medium |
Yes | Provided by Embrace | Marketing medium classification used for partner channel attribution. | affiliate-network |
term |
No | Partner defined | Freeform term for internal ad keyword / sub-channel segmentation. | spring-keyword-1 |
content |
No | Partner defined | Distinguishes creative variations (A/B test, banner vs. text). | banner-300x250 |
campaign |
No | Partner (runtime) | Your campaign / promo / slogan identifier. | spring-2025-launch |
source |
Yes | Provided by Embrace | High-level traffic source identifier allocated by Embrace. | partner-portal |
Overwrite Semantics
- Full Replacement: The server does not merge partial analytics objects. Send ALL desired fields every time you submit a quote request.
- Omission = Clear: Leaving out the
analyticsblock (or a specific field inside it) when re‑posting will result in that data no longer being associated with the current quote state. - Consistency: For multi-step journeys (add pet, update coverage, change frequency) persist and resend the same analytics object unless intentionally changing attribution.
Best Practices
- Persist analytics client‑side (e.g., localStorage/session) after first submission so later modifications can resend it reliably.
- Validate required keys (
medium,campaign,source) before initial submission; reject empty strings. - Avoid PII—these fields are for attribution only.
- Normalize casing (e.g., lower-kebab) for easier downstream aggregation.
- Log original + updated analytics values around each POST for audit.
Minimal Example With Analytics
{
"analytics": {
"medium": "affiliate-network",
"term": "keyword-group-a",
"content": "banner-1",
"campaign": "spring-2025-launch",
"source": "partner-portal"
},
"contact": { "ratingZipCode": "44114", "email": "owner@example.com", "brand": "embrace" },
"pets": [ { "name": "Riley", "breedId": 452, "gender": "Female", "age": "Two" } ]
}
Example: Unintentionally Clearing Analytics
If the initial request included analytics (above) but a later update omits it:
{
"contact": { "ratingZipCode": "44114", "email": "owner@example.com", "brand": "embrace" },
"pets": [ { "name": "Riley", "breedId": 452, "gender": "Female", "age": "Two" } ]
}
Result: Stored analytics attribution will be cleared for the quote.
Payment Frequency
Field path: contact.billingInformation.paymentFrequency
Accepted values (exact capitalization required):
"Monthly"(default when omitted) – Premium fields reflect the month-to-month billing scenario (e.g.,monthlyPremium,paymentDueRecurring)."Yearly"– The SAME premium fields are reused to represent the full annual amounts (no separate annual field names introduced).
If you omit the field the API assumes Monthly. Use Yearly to present a single pay‑in‑full option; only your UI labels change.
Need to change the payment frequency after quoting without rebuilding the entire payload? Use the lightweight Update Payment Frequency endpoint.
Minimal Example (Monthly default)
{
"contact": {
"ratingZipCode": "44114",
"email": "owner@example.com",
"phoneNumber": "555-123-1234",
"brand": "embrace"
},
"pets": [
{ "name": "Riley", "breedId": 452, "gender": "Female", "age": "Two" }
]
}
Explicit Yearly Example
{
"contact": {
"ratingZipCode": "44114",
"email": "owner@example.com",
"phoneNumber": "555-123-1234",
"brand": "embrace",
"billingInformation": {
"paymentFrequency": "Yearly"
}
},
"pets": [
{ "name": "Riley", "breedId": 452, "gender": "Female", "age": "Two" }
]
}
UI Guidance
- Provide a toggle (Monthly / Annual) before quote submission so you only need one API call per mode.
- Cache the last-used frequency in local storage or session to persist user preference.
Validation Notes
- Only accept
MonthlyorYearly; reject or default any other casing/values. - Switching between modes requires only relabeling in the UI—no different field extraction.
- If an unsupported value is sent, expect validation failure; sanitize before calling the API.
- For pre-validating address/email inputs before quoting, see Validation Endpoints.
Rate Shopping Overview
rateShopCoverageSelections lets you ask the API to price (“rate shop”) specific coverage combinations up front.
Result Location: The calculated results are returned in the top-level
rateShopQuoteResultsarray of theQuoteResponse. Each element corresponds positionally to a coverage selection you sent (index-aligned with the input array) and contains its owncoverageSelection,premiumSummary, andpetCoverages.
Authoritative schema (always check for newest values): CoverageSelection Definition
Each element in rateShopCoverageSelections represents one coverage configuration you want premium data for. The API responds with the calculated premiums, allowing you to build a coverage picker without making multiple quote calls.
Accepted Value Forms
For the four primary numeric/enum style fields you may pass either:
- The canonical word form (e.g.,
FourHundredFifty), OR - The numeric form AS A STRING (e.g.,
"450").
Important: Send both forms as JSON strings. Do not send bare numbers (e.g., 450 without quotes). The API accepts the numeric variant only when provided as a string token.
For the authoritative, most current list of allowed values (and any future additions), always refer to the live schema: CoverageSelection Definition
| Field | String Forms | Numeric Forms | Notes |
|---|---|---|---|
| reimbursementPercentage | Seventy, Eighty, Ninety |
"70", "80", "90" |
Percent of eligible costs reimbursed |
| annualWellnessReward | None, TwoHundredFifty, ThreeHundred, FourHundredFifty, FiveHundred, SixHundredFifty, SevenHundred |
"0", "250", "300", "450", "500", "650", "700" |
None/"0" = no wellness add‑on |
| annualDeductible | OneHundred, TwoHundred, TwoHundredFifty, ThreeHundred, FiveHundred, SevenHundredFifty, OneThousand |
"100", "200", "250", "300", "500", "750", "1000" |
Deductible before reimbursement |
| annualReimbursementLimit | TwoThousand, FiveThousand, EightThousand, TenThousand, FifteenThousand, ThirtyThousand, Unlimited |
"2000", "5000", "8000", "10000", "15000", "30000", "-1" |
Unlimited represented as "-1" |
Boolean flags: examFeeCoverage, drugDentalCoverage (true / false).
Example Request Fragment
{
"rateShopCoverageSelections": [
{
"reimbursementPercentage": "Eighty",
"annualWellnessReward": "450",
"annualDeductible": "500",
"annualReimbursementLimit": "Unlimited",
"examFeeCoverage": true,
"drugDentalCoverage": false
},
{
"reimbursementPercentage": "90",
"annualWellnessReward": "None",
"annualDeductible": "300",
"annualReimbursementLimit": "15000",
"examFeeCoverage": false,
"drugDentalCoverage": true
}
]
}
Interpreting Results
Each element in rateShopQuoteResults contains:
coverageSelection– Echo of the selection that was rated.premiumSummary– Pricing snapshot for that combination.petCoverages– Per-pet pricing details.
Example response fragment:
{
"rateShopQuoteResults": [
{
"coverageSelection": {
"reimbursementPercentage": "Eighty",
"annualDeductible": "500",
"annualReimbursementLimit": "Unlimited",
"annualWellnessReward": "450",
"examFeeCoverage": true,
"drugDentalCoverage": false
},
"premiumSummary": { /* ...pricing fields... */ },
"petCoverages": [ /* per-pet details */ ]
}
]
}
Best Practices
- Request no more than 50 combinations per call (practical UI performance + payload size).
- Persist
rateShopQuoteResultsclient-side to avoid unnecessary re-quotes during a single user session.
Validation & Re-Quote Triggers
- Validate string tokens (avoid typos like
Seventyy). - Reject unsupported numeric strings (e.g.,
"475"). - Make a new
POSTrequest to thefullquoteendpoint when pets change, a new combination is needed, or data is stale.
Feedback
Was this page helpful?
Glad to hear it! Please tell us how we can improve.
Sorry to hear that. Please tell us how we can improve.